package com.ironman.analyze.core.compute.factory;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.util.StrUtil;
import com.ironman.analyze.common.dataobject.TrainingData;
import com.ironman.common.entity.*;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Slf4j
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class OriginalDataFactory {

    public static OriginalDataWrapper build(List<TrainingData> trainingDataList,
                                            int windWindowSize,
                                            int headingWindowSize,
                                            int speedWindowSize,
                                            int heartrateWindowSize,
                                            int rolWindowSize,
                                            int yawWindowSize) {

        List<Tuple> tupleList = new ArrayList<>();

        List<GpsData> gpsDataList = new ArrayList<>();
        List<HeadingData> headingDataList = new ArrayList<>();
        List<SpeedData> speedDataList = new ArrayList<>();

        List<HeartrateData> heartrateDataList1 = new ArrayList<>();
        List<HeartrateData> heartrateDataList2 = new ArrayList<>();

        List<RolData> rolDataList = new ArrayList<>();
        List<YawData> yawDataList = new ArrayList<>();

        int maxWindowSize = ListUtil.of(windWindowSize, headingWindowSize, speedWindowSize, heartrateWindowSize, rolWindowSize, yawWindowSize).stream().max(Integer::compare).orElse(0);

        int dropHeadingWindowSize = maxWindowSize - headingWindowSize;
        int dropSpeedWindowSize = maxWindowSize - speedWindowSize;
        int dropHeartrateWindowSize = maxWindowSize - heartrateWindowSize;
        int dropRolWindowSize = maxWindowSize - rolWindowSize;
        int dropYawWindowSize = maxWindowSize - yawWindowSize;

        for (TrainingData trainingData : trainingDataList) {
            Date ts = trainingData.getTs();
            if (maxWindowSize == 1) {
                String trainingBoatCode = trainingData.getTrainingBoatCode();
                if (StrUtil.isNotBlank(trainingBoatCode)) {
                    tupleList.add(new Tuple(ts, trainingBoatCode));
                }
                if (Boolean.TRUE.equals(trainingData.getValid())) {
                    gpsDataList.add(new GpsData(ts, trainingData.getLongitude(), trainingData.getLatitude()));
                } else {
                    gpsDataList.add(new GpsData(ts, null, null));
                }
            } else {
                maxWindowSize -= 1;
            }

            if (dropHeadingWindowSize == 0) {
                if (Boolean.TRUE.equals(trainingData.getValid())) {
                    headingDataList.add(new HeadingData(ts, trainingData.getGpsDirection(), trainingData.getDeclination()));
                } else {
                    headingDataList.add(new HeadingData(ts, null, null));
                }
            } else {
                dropHeadingWindowSize -= 1;
            }

            if (dropSpeedWindowSize == 0) {
                if (Boolean.TRUE.equals(trainingData.getValid())) {
                    speedDataList.add(new SpeedData(ts, trainingData.getGpsSpeed()));
                } else {
                    speedDataList.add(new SpeedData(ts, null));
                }
            } else {
                dropSpeedWindowSize -= 1;
            }

            if (dropHeartrateWindowSize == 0) {
                String heartRate = trainingData.getHeartRate();
                if (StrUtil.isBlank(heartRate)) {
                    heartrateDataList1.add(new HeartrateData(ts, null));
                    heartrateDataList2.add(new HeartrateData(ts, null));
                } else {
                    String[] split = heartRate.contains(",") ? heartRate.split(",") : heartRate.split("\\|");
                    heartrateDataList1.add(new HeartrateData(ts, Integer.parseInt(split[0])));
                    heartrateDataList2.add(new HeartrateData(ts, Integer.parseInt(split[1])));
                }
            } else {
                dropHeartrateWindowSize -= 1;
            }

            if (dropRolWindowSize == 0) {
                String rol = trainingData.getRol();
                if (StrUtil.isBlank(rol)) {
                    rolDataList.addAll(IntStream.of(10).mapToObj(n -> new RolData(ts, null)).collect(Collectors.toList()));
                } else {
                    rolDataList.addAll(Arrays.stream(rol.split("\\|")).map(n -> new RolData(ts, Double.parseDouble(n))).collect(Collectors.toList()));
                }
            } else {
                dropRolWindowSize -= 1;
            }

            if (dropYawWindowSize == 0) {
                String yaw = trainingData.getYaw();
                if (StrUtil.isBlank(yaw)) {
                    yawDataList.addAll(IntStream.of(10).mapToObj(n -> new YawData(ts, null)).collect(Collectors.toList()));
                } else {
                    yawDataList.addAll(Arrays.stream(yaw.split("\\|")).map(n -> new YawData(ts, Double.parseDouble(n))).collect(Collectors.toList()));
                }
            } else {
                dropYawWindowSize -= 1;
            }
        }

        return OriginalDataWrapper.builder()
                .tupleList(tupleList)
                .gpsDataList(gpsDataList)
                .headingDataList(headingDataList)
                .speedDataList(speedDataList)
                .heartrateDataList1(heartrateDataList1)
                .heartrateDataList2(heartrateDataList2)
                .rolDataList(rolDataList)
                .yawDataList(yawDataList)
                .build();
    }
}
